package com.ccp.dev.form.table;

import com.ccp.dev.core.basic.db.datasource.DbContextHolder;
import com.ccp.dev.core.basic.table.BaseTableMeta;
import com.ccp.dev.core.basic.table.IDbView;
import com.ccp.dev.core.basic.table.SqlTypeConst;
import com.ccp.dev.core.basic.table.impl.*;
import com.ccp.dev.core.util.AppUtil;
import com.ccp.dev.core.util.StringUtil;
import com.ccp.dev.form.consts.FormConstants;
import com.ccp.dev.system.model.SysDataSource;
import com.ccp.dev.system.service.SysDataSourceService;

import javax.annotation.Resource;

/**
 * 元数据读取工厂。
 *
 * @author caishaofan
 */
public class TableMetaFactory {

    /**
     * 根据数据源别名获取表元素据读取对象。 这里使用了简单工厂。
     *
     * @param alias          数据源别名
     * @param dataSourceType 数据源类型
     * @return BaseTableMeta 类型
     * @throws Exception 异常
     */
    public static BaseTableMeta getMetaData(String alias, String dataSourceType) throws Exception {

        String dbType = getDbTypeBySysDataSourceAlias(alias, dataSourceType);
        BaseTableMeta meta;
        if (dbType.equals(SqlTypeConst.ORACLE)) {
            meta = AppUtil.getBean(OracleTableMeta.class);
        } else if (dbType.equals(SqlTypeConst.MYSQL)) {
            meta = AppUtil.getBean(MySqlTableMeta.class);
        } else if (dbType.equals(SqlTypeConst.SQLSERVER)) {
            meta = AppUtil.getBean(SqlServerTableMeta.class);
        } else if (dbType.equals(SqlTypeConst.DB2)) {
            meta = AppUtil.getBean(Db2TableMeta.class);
        } else if (dbType.equals(SqlTypeConst.H2)) {
            meta = AppUtil.getBean(H2TableMeta.class);
        } else if (dbType.equals(SqlTypeConst.DM)) {
            meta = AppUtil.getBean(DmTableMeta.class);
        } else if (dbType.equals(SqlTypeConst.POSTGRESQL)) {
            meta = AppUtil.getBean(PostgreSqlTableMeta.class);
        } 
//        else if (dbType.equals(SqlTypeConst.GBASE)) {
//            meta = AppUtil.getBean(MySqlTableMeta.class);
//        } 
        else {
            throw new Exception(FormConstants.STR_UNKNOWN_DATABASE_TYPE);
        }
        DbContextHolder.setDataSource(alias, dbType);
        return meta;
    }

    /**
     * 根据数据源获取
     *
     * @param dsName         数据源别名
     * @param dataSourceType 数据源类型
     * @return IDbView
     * @throws Exception 异常
     */
    public static IDbView getDbView(String dsName, String dataSourceType) throws Exception {
        String dbType = getDbTypeBySysDataSourceAlias(dsName, dataSourceType);
        IDbView meta = null;
        if (dbType.equals(SqlTypeConst.ORACLE)) {
            meta = AppUtil.getBean(OracleDbView.class);
        } else if (dbType.equals(SqlTypeConst.SQLSERVER)) {
            meta = AppUtil.getBean(SqlserverDbView.class);
        } else if (dbType.equals(SqlTypeConst.MYSQL)) {
            meta = AppUtil.getBean(MysqlDbView.class);
        } else if (dbType.equals(SqlTypeConst.DB2)) {
            meta = AppUtil.getBean(Db2DbView.class);
        } else if (dbType.equals(SqlTypeConst.H2)) {
            meta = AppUtil.getBean(H2DbView.class);
        } else if (dbType.equals(SqlTypeConst.DM)) {
            meta = AppUtil.getBean(DmDbView.class);
        } else if (dbType.equals(SqlTypeConst.POSTGRESQL)) {
            meta = AppUtil.getBean(PostgreSqlDbView.class);
        } else {
            throw new Exception(FormConstants.STR_UNKNOWN_DATABASE_TYPE);
        }
        DbContextHolder.setDataSource(dsName, dbType);
        return meta;
    }

    /**
     * 根据别名从sys_Data_Source中找出对应的数据类型，默认是本地数据源
     *
     * @param alias          别名
     * @param dataSourceType 类型
     * @return String
     */
    public static String getDbTypeBySysDataSourceAlias(String alias, String dataSourceType) {
        //用这个因为本方法是一个静态方法@Resource private SysDataSourceService sysDataSourceService不能直接调用;
        SysDataSourceService sysDataSourceService = (SysDataSourceService) AppUtil.getBean(SysDataSourceService.class);
        if (StringUtil.isEmpty(alias)) {
            //(添加外部表别名不可能为空)如果别名为空 返回默认的数据源类型
            return dataSourceType;
        }
        //根据别名查询数据源，如果没有 返回默认的数据源类型
        SysDataSource sysDataSource = sysDataSourceService.getByAliasAndId(alias, null);
        if (sysDataSource != null) {
            dataSourceType = sysDataSource.getDbType();
        }
        return dataSourceType;
    }
}
